package learn;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;

/**
 * 阻塞队列
 * 在普通队列的基础上实现了线程安全
 * 对与服务器按之前亲求的交互，可能因为前端服务器的请求一下子过于多了
 * 导致后端的服务器来不及以下值处理如此多的请求，导致服务器崩溃的情况
 * 为避免这样的情况就可以将请求储存到阻塞队列中，然后由阻塞队列将请求再以一个合理的量
 * 传递给后端，这样可以起到一个削峰填谷的效果，就像是三峡大坝一样
 */

public class blockQueue {

    public static void main(String[] args) {

    }
    public static void main1(String[] args) {
        //自带的阻塞队列
        BlockingQueue<String> block = new ArrayBlockingQueue<>(10);
        BlockingQueue<String> bolck1 = new PriorityBlockingQueue<>();
        BlockingQueue<String> bolck2 = new LinkedBlockingQueue<>();

    }
    public static void main0(String[] args) throws InterruptedException{
        myQueue t1 = new myQueue(4);
        t1.put(1);
        t1.put(2);
        t1.put(3);
        t1.take();
        t1.take();
        t1.take();
        t1.take();
        System.out.println(t1.getSize());
    }
}

/**
 * 循环队列
 */
class myQueue {
    Object locker = new Object();//锁
    private final int DEFAULT_SPACE = 10;
    private int[] arr;
    int end = 0;
    int top = 0;
    int size = 0;

    public myQueue() {
        arr = new int[DEFAULT_SPACE];
    }

    public myQueue(int capacity) {
        arr = new int[capacity + 1];
    }

    public void put(int val)  {
        while(isFull()) {//如果满了，那么就要wait等待他把元素出出去 用while来进行二次判断
            //使用while是为了保证出这个循环得队列一定不是满得，而且如果用if的化可能会出现interrupt提前唤醒wait
            //这样就不能确保队列一定是不为满的情况
            try {
                locker.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();//可能是通过interrupt唤醒得
            }
        }
        arr[top++] = val;
        size++;
        locker.notify();//唤醒take
        if (top >= arr.length) {
            top = 0;
        }
    }

    public int take() {
        while (isEmpty()) {
            try {
                locker.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        int ret = arr[end];

        end++;
        size--;
        locker.notify();//唤醒put
        if (end >= arr.length) {
            end = 0;
        }
        return ret;
    }

    public boolean isFull() {
        return (top + 1) % arr.length == end;
    }

    public boolean isEmpty() {
        return top == end;
    }

    public int getSize() {
        return size;
    }
}